Amazon Redshift データ共有の書き込みクエリのサポートを試す!(プレビュー) #AWSreInvent
データアナリティクス事業本部のコンサルティングチームの石川です。
re:Invent2023でAmazon Redshiftのデータ共有を介した複数のデータウェアハウスからの書き込みクエリのサポートが発表されました。このアップデートでAWSアカウント内またはアカウント間で読み取りと書き込みの両方のクエリをデータ共有で実行できるようになりました。(プレビュー段階では、同じAWSアカウント内となります。)
執筆時点ではプレビューですが、早速試してみます。なお、プレビュー機能は、主に評価とテストのために提供されるものです。本番システムでは使用しないでください。
Redshift のデータ共有(Data Sharing)とは
Redshift間でデータのコピーや移動することなくデータを共有するサービスで、Amazon Redshift間でライブデータを素早くデータアクセスが可能になります。データ共有はデータへのライブアクセスを提供するため、データが更新されてもユーザーは常に最新の一貫性のある情報を見ることができます。
コンシューマーRedshift(共有される側のRedshift)の共有データにアクセスできるユーザーとグループは、標準のSQLおよび分析ツールを使用して、高性能でデータを検出およびクエリできます。データ共有により、共有データにアクセスするワークロードは互いに分離されます。Amazon Redshiftでデータ共有を使用するための追加コストはありません。
今回のアップデータでは、読み込みに加えて書き込みもサポートしました。
用語の定義
データ共有
データを共有するプロデューサーは、CREATE DATASHARE <sharename>
コマンドを使用して1つ以上のデータ共有を作成します。データを共有する単位をデータ共有と呼びます。
データ共有オブジェクト
上記のデータ共有に追加したプロデューサーのオブジェクト(テーブルやビューなど)をデータ共有オブジェクトと呼びます。
プロデューサーRedshift
データを共有するRedshiftを表します。Producer-Consumerパターンのプロデューサーです。
コンシューマーRedshift
データを共有されるRedshiftを表します。Producer-Consumerパターンのコンシューマーです。
名前空間ID(Namespace ID)
ネームスペース毎に付与されたユニークな識別子。
検証環境
検証用Redshift Serverlessのワークスペース
Amazon Redshift のデータ共有による複数のウェアハウスからの書き込みに対するサポートは、PREVIEW_2023 トラックを利用できるすべてのリージョンで、このトラックを使用する ra3.4xl クラスター、ra3.16xl クラスター、サーバーレスワークグループでご利用いただけます。
今回は、Redshift Serverlessでお気軽に試したいと思ったのですが、メンテナンストラックのPREVIEW_2023
はどこで設定するのか分からず、途方に暮れていたところマネジメントコンソールの上にそれらしいボタンを発見、後は普通にワークスペースを作成できました。
今回は、2つのRedshift Serverlessワークスペースを作成しました。
- プロデューサーのRedshift: preview-producer-ns
- 名前空間ID(Namespace ID):810c95ce-d813-4219-a42c-40f385dcea75
- コンシューマーのRedshift: preview-consumer-ns
- 名前空間ID(Namespace ID):0e1a85a3-607d-4b3d-a762-0f10bdde84c7
Redshiftのデータ共有(Data Sharing)では、共有する側(以降、Producerと呼びます)と共有される側(以降、Consumerと呼びます)を2つのRedshiftを準備します。
検証シナリオ
今回は、プロデューサーワークスペースのticketスキーマとそのテーブルのデータ共有を作成して、コンシューマーRedshiftに共有します。コンシューマーRedshiftでは、共有されたデータ共有を用いてデータベースを定義します。
データ共有の作成・設定
プロデューサーRedshiftの設定
データ共有するスキーマ・テーブルの準備
サクッと、サンプルのデータを用意したいので、sample_data_devデータベースのテーブルをコピーします。
dev=# CREATE SCHEMA tickit; CREATE SCHEMA dev=# CREATE TABLE tickit.users AS SELECT * FROM sample_data_dev.tickit.users; CREATE TABLE
データ共有の作成
最初にデータ共有を作成します。ここで作成した「データ共有」という器にスキーマやテーブルを追加します。
dev=# CREATE DATASHARE tickit_datashare; CREATE DATASHARE dev=# ALTER DATASHARE tickit_datashare SET publicaccessible = TRUE; ALTER DATASHARE
tickit_datashareに対して、CREATE, USAGEを許可します。
dev=# SET search_path TO tickit; SET dev=# GRANT CREATE, USAGE ON SCHEMA tickit TO DATASHARE tickit_datashare; GRANT
データ共有にtickitスキーマの各テーブルを追加
データ共有に共有したいテーブルを追加します。tickit_datashare.userに対して、SELECTとINSERTを付与します。← 読み(SELECT)、書き込み(INSERT)できる。
dev=# GRANT SELECT, INSERT ON TABLE tickit.users TO DATASHARE tickit_datashare; GRANT
作成したデータ共有をコンシューマーRedshiftに共有する
作成したデータ共有は、コンシューマーRedshiftのNAMESPACEを指定して共有します。
dev=# GRANT USAGE ON DATASHARE tickit_datashare TO NAMESPACE '0e1a85a3-607d-4b3d-a762-0f10bdde84c7'; GRANT
これでプロデューサーRedshiftのデータ共有の共有設定は完了です。マネジメントコンソールからはこのように確認できます。
データ共有名(tickit_datashare)をクリックすると、詳細を確認できます。
データ共有したコンシューマーRedshift一覧
プロデューサーRedshiftで作成したデータ共有をどのコンシューマーRedshiftに共有したかを確認できます。
dev=# SELECT * FROM svv_datashare_consumers; -[ RECORD 1 ]------+------------------------------------- share_name | tickit_datashare consumer_account | consumer_namespace | 0e1a85a3-607d-4b3d-a762-0f10bdde84c7 share_date | 2023-12-26 12:45:48
マネジメントコンソールからはこのように確認できます。
コンシューマーRedshiftの設定
データ共有の一覧の確認
データ共有の一覧を確認します。コンシューマーRedshiftなのでプロデューサーRedshiftが共有してくれたデータ共有が表示されます。コンシューマーRedshiftはデータ共有を参照しているので、share_typeはINBOUND
です。
dev=# SELECT * FROM svv_datashares; -[ RECORD 1 ]-------+----------------------------------------------------------------- share_name | tickit_datashare share_id | share_owner | source_database | consumer_database | share_type | INBOUND createdate | is_publicaccessible | t share_acl | producer_account | 123456789012 producer_namespace | 810c95ce-d813-4219-a42c-40f385dcea75 managed_by |
データ共有のオブジェクト一覧
データ共有のオブジェクト一覧も同様に確認できます。コンシューマーRedshiftはデータ共有しているので、share_typeはINBOUND
です。
dev=# SELECT * FROM svv_datashare_objects; -[ RECORD 1 ]------+------------------------------------- share_type | INBOUND share_name | tickit_datashare object_type | table object_name | tickit.users producer_account | 123456789012 producer_namespace | 810c95ce-d813-4219-a42c-40f385dcea75 include_new | -[ RECORD 2 ]------+------------------------------------- share_type | INBOUND share_name | tickit_datashare object_type | schema object_name | tickit producer_account | 123456789012 producer_namespace | 810c95ce-d813-4219-a42c-40f385dcea75 include_new |
データ共有からデータベースを作成
データ共有からデータベースを作成して、共有されたデータの参照します。データベースを作成を作成する際には、プロデューサーRedshiftのNAMESPACEとデータ共有でデータベースを作成します。
dev=# CREATE DATABASE consumer_tickit FROM DATASHARE tickit_datashare OF NAMESPACE '810c95ce-d813-4219-a42c-40f385dcea75'; CREATE DATABASE
adminユーザーに作成したデータベースの使用許可を付与
作成したデータベースを参照するにはデータベースの使用許可を付与しなければなりません。
dev=# GRANT USAGE ON DATABASE consumer_tickit TO admin; GRANT
これでコンシューマーRedshiftのデータ共有の共有設定も完了です。
共有データの参照
次は、共有されたデータを参照してみます。Redshiftに接続する際に指定したデータベースによって、データへのアクセス方法が異なります。
別のデータベースからデータを参照
デフォルトのdevデータベースからアクセスする場合は、<database>.<schema>.<object>の3つをドットで修飾した表記法で参照します。所謂、Cross-Databaseです。以下の例では、テーブルのエイリアスを指定してクエリの記述を簡素化しています。
dev=# SELECT * FROM consumer_tickit.tickit.users limit 1; -[ RECORD 1 ]-+-------------------------------- userid | 7 username | OWY35QYB firstname | Tamekah lastname | Juarez city | Moultrie state | WV email | elementum@semperpretiumneque.ca phone | (297) 875-7247 likesports | liketheatre | likeconcerts | likejazz | t likeclassical | t likeopera | f likerock | likevegas | likebroadway | f likemusicals | f
データ共有内のオブジェクトへの書き込み
データ共有内のオブジェクトに書き込む方法
プレビューの段階では、データ共有内のオブジェクトに書き込む方法は 2 つあります。なお、将来的には、<database>.<schema>.<object>の3つをドットで修飾した表記法もサポートする予定との記載がありました。
- USE コマンドを使用してローカル データベースに接続する
- Redshift JDBC、ODBC、または Python ドライバーを介して datashares データベースに直接接続します
今回は、1の「USE コマンドを使用してローカル データベースに接続する」方法でデータ共有内のオブジェクトへの書き込みを試みます。
USEコマンドを使用すると、<schema>.<object>の2つをドットで修飾した表記法でデータ共有オブジェクトをクエリし、複数ステートメントのトランザクションを実行できます。複数ステートメントのトランザクションは単一データベース内でのみ実行できます。
USE datashare database;
RESET USE コマンドを実行すると、接続しているデータベースの使用に戻ることができます。
RESET USE;
だが、しかし、、、USE
うまくいきませんでした。きっと、私が全て悪いと思います。試行錯誤は、以下のとおりです。
dev=# USE datashare database; ERROR: syntax error at or near "datashare" LINE 1: USE datashare database; ^ dev=# USE consumer_tickit database; ERROR: syntax error at or near "database" LINE 1: USE consumer_tickit database; ^ dev=# USE datashare consumer_tickit; ERROR: syntax error at or near "datashare" LINE 1: USE datashare consumer_tickit; ^ dev=# USE tickit_datashare consumer_tickit; ERROR: syntax error at or near "consumer_tickit" LINE 1: USE tickit_datashare consumer_tickit; ^ dev=# RESET USE; RESET
ということでした、、、でも諦めない。「...将来的には、<database>.<schema>.<object>の3つをドットで修飾した表記法もサポートする予定...」って、あったので試したところうまくいきました。
ので、今日はサポートしていないはずの3つをドットで修飾した表記法で、クエリを実行します。(我ながら、力技感ハンパないな。)
オブジェクトの書き込み(テーブル追加)
プロデューサーで、CREATE
を許可したので、テーブル追加できるか試してみます。
まず、コンシューマーでCREATE TABLE
を実行します。SELECT
でテーブルに対してクエリできた、つまりテーブルが作成できたことが確認できました。
dev=# CREATE TABLE consumer_tickit.tickit.ishikawa (id int, name varchar(256)); CREATE TABLE dev=# SELECT * FROM consumer_tickit.tickit.ishikawa; id | name ----+------ (0 rows)
では、プロデューサーでテーブルを確認します。
dev=# SELECT * FROM tickit.ishikawa; id | name ----+------ (0 rows)
見えました、つまりコンシューマーで作成したテーブル(書き込み)がプロデューサーで確認できたことになります。
いい感じだぞ、この調子だ!
オブジェクトの書き込み(テーブルのレコード追加)
プロデューサーで、INSERT
を許可したので、テーブルのレコード追加できるか試してみます。
まず、コンシューマーでINSERT INTO
を実行します。
dev=# INSERT INTO consumer_tickit.tickit.ishikawa (id, name) VALUES(1, 'consumer'); INSERT 0 1 dev=# SELECT * FROM consumer_tickit.tickit.ishikawa; id | name ----+---------- 1 | consumer (1 row)
INSERT INTO
できたことが確認できました。
では、プロデューサーでテーブルを確認します。
見えました、つまりコンシューマーで作成したテーブルに対してデータの追加(書き込み)がプロデューサーで確認できたことになります。
dev=# SELECT * FROM tickit.ishikawa; id | name ----+---------- 1 | consumer (1 row)
ちなみに、オブジェクトオーナーを確認したところ、ややこしい感じになっています。オブジェクトオーナーは、プロデューサーの方で適切に変更したほうが良さそうですね。
dev=# SET search_path TO tickit; SET dev=# \d List of relations schema | name | type | owner --------+----------+-------+---------------------------------------------------------- tickit | ishikawa | table | ds:tickit_datashare_nsp_0e1a85a3607d4b3da7620f10bdde84c7 tickit | users | table | admin (2 rows)
では、さらに調子に乗って、プロデューサーからテーブルに対してデータの追加(書き込み)してみます。
dev=# INSERT INTO tickit.ishikawa (id, name) VALUES(2, 'producer'); INSERT 0 1 dev=# SELECT * FROM tickit.ishikawa; id | name ----+---------- 1 | consumer 2 | producer (2 rows)
オブジェクトオーナーではありませんが、データベース管理ユーザーなので、問題なく書き込みできました。つまり、相互に書き込み(INSERT)できるということです。
コンシューマーからも確認できました。バッチリですね。
dev=# select * from consumer_tickit.tickit.ishikawa; id | name ----+---------- 1 | consumer 2 | producer (2 rows)
なお、クエリエディタv2からもテーブルが見えています。
最後に
今回は、同じAWSアカウントに2つのRedshift Serverlessを用意して検証しました。
まだ、プレビューの段階ですので、データ共有の要件と制限などありますが、データ共有によるテーブルの作成(CREATE)と更新(INSERT)が動作することが確認できました。
さまざまなテーブルに対して SELECT、INSERT、UPDATE などの権限を付与したり、さまざまなスキーマに対して USAGE や CREATE などの権限を付与したりできることも確認しました。
また、アカウント間でデータを共有する場合、プロデューサー アカウント管理者は、これらのアカウントがデータへの読み取り専用アクセスにするかどうかを選択でき、さらに、プロデューサー アカウント管理者は、特定の名前空間またはリージョンに読み取り専用、読み取りおよび書き込み、またはデータへのアクセスを許可するかどうかを決定できることも確認できました。
下記のマニュアルによると、データはライブであり、書き込みトランザクションがコミットされるとすぐにすべてのウェアハウスで利用できるようになるそうです。USEコマンドについては、一般提供開始(GA)になったら確認したいと思います。